#pragma once
#include "api.hpp"

namespace opengl {

class buffer {
public:
    // Constructors
    OPENGLAPI buffer();
    OPENGLAPI buffer(const buffer &) = delete;
    OPENGLAPI buffer(buffer &&other);
    OPENGLAPI buffer(u64 size, const void *data = nullptr, u32 flags = flags::dynamic_storage_bit);
    OPENGLAPI void create(u64 size, const void *data = nullptr, u32 flags = flags::dynamic_storage_bit);
    OPENGLAPI static buffer copy_from(const buffer &other);

    // Member functions
    OPENGLAPI void bind(u32 target) const;               // glBindBuffer
    OPENGLAPI void bind_to(u32 target, u32 index) const; // glBindBufferBase
    OPENGLAPI void set_data(const void *data, u64 size, u64 offset = 0) const;

    // Operator overloads
    OPENGLAPI buffer &operator=(const buffer &) = delete;
    OPENGLAPI buffer &operator=(buffer &&other);

    // Destructor
    OPENGLAPI ~buffer();

public:
    enum flags : u32 {
        dynamic_storage_bit = 0x0100,
        client_storage_bit = 0x0200,
        map_read_bit = 0x0001,
        map_write_bit = 0x0002,
        map_persistent_bit = 0x0040,
        map_coherent_bit = 0x0080,
    };

    enum target : u32 {
        array_buffer = 0x8892,
        element_array_buffer = 0x8893,
        uniform_buffer = 0x8A11,
        shader_storage_buffer = 0x90D2,
        pixel_pack_buffer = 0x88EB,
        pixel_unpack_buffer = 0x88EC,
        transform_feedback_buffer = 0x8C8E,
        atomic_counter_buffer = 0x92C0,
    };

public:
    u32 id;
};

} // namespace opengl